﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace ShevaEngine.Core.Modules.Graphics
{
    /// <summary>
    /// Draw call key.
    /// </summary>
    [StructLayout(LayoutKind.Explicit)]
    public struct DrawCallKey 
    {
        /// <summary>
        /// None DrawCallKey.
        /// </summary>
        public static readonly DrawCallKey NoneDrawCallKey = new DrawCallKey()
        {
            MaterialID = DrawCallKey.None,
            TextureState = DrawCallKey.None,
            MaterialParamsID = DrawCallKey.None,
            BuffersID = DrawCallKey.None
        };

        /// <summary>None.</summary>
        public const UInt16 None = UInt16.MaxValue;

        /// <summary>Material Id.</summary>
        [FieldOffset(6)]
        public UInt16 MaterialID;
        /// <summary>Texture state.</summary>
        [FieldOffset(4)]
        public UInt16 TextureState;
        /// <summary>Material parameters ID..</summary>
        [FieldOffset(2)]
        public UInt16 MaterialParamsID;
        /// <summary>Buffers ID.</summary>
        [FieldOffset(0)]
        public UInt16 BuffersID;
        /// <summary>ID.</summary>
        [FieldOffset(0)]
        public Int64 ID;
        

        /// <summary>
        /// Konstruktor.
        /// </summary>
        public DrawCallKey(UInt16 materialID, UInt16 textureState, UInt16 materialParamsID, UInt16 buffersID)
        {
            this.ID = 0;
            this.MaterialID = materialID;
            this.TextureState = textureState;
            this.MaterialParamsID = materialParamsID;
            this.BuffersID = buffersID;            
        }

        /// <summary>
        /// Clone.
        /// </summary>
        /// <returns></returns>
        public DrawCallKey Clone()
        {
            return new DrawCallKey(this.MaterialID, this.TextureState, this.MaterialParamsID, this.BuffersID);
        }

        /// <summary>
        /// Operator ==.
        /// </summary>
        /// <param name="key1"></param>
        /// <param name="key2"></param>
        /// <returns></returns>
        public static bool operator ==(DrawCallKey key1, DrawCallKey key2)
        {
            return key1.ID == key2.ID;
        }

        /// <summary>
        /// Operator !=.
        /// </summary>
        /// <param name="key1"></param>
        /// <param name="key2"></param>
        /// <returns></returns>
        public static bool operator !=(DrawCallKey key1, DrawCallKey key2)
        {
            return key1.ID != key2.ID;
        }
    }

    /// <summary>
    /// Draw call key comparer.
    /// </summary>
    public class DrawCallKeyComparer : IComparer<DrawCallKey>
    {
        /// <summary>
        /// Compare method.
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public int Compare(DrawCallKey x, DrawCallKey y)
        {            
            return Math.Sign(x.ID - y.ID);

            /*return Math.Sign((long)(x1 - y1));
            //return (int)(x.ID - y.ID);

            int diff = x.MaterialID - y.MaterialID;

            if (diff == 0)
            {
                diff = x.TextureState - y.TextureState;

                if (diff == 0)
                {
                    diff = x.MaterialParamsID - y.MaterialParamsID;

                    if (diff == 0)
                    {
                        return x.BuffersID - y.BuffersID;
                    }
                    else
                        return diff;
                }
                else
                    return diff;
            }
            else
                return diff;*/
        }
    }
}
